subscribe  订阅

Discovering features using HTTP OPTIONS
使用 HTTP OPTIONS 发现功能

Say you have an API, and you want to communicate what sort of things a user can do on a specific endpoint. You can use external description formats like OpenAPI or JSON Schema, but sometimes it’s nice to also dynamically communicate this on the API itself.
假设你有一个 API,并且你想传达用户可以在特定端点上执行哪些作。您可以使用外部描述格式,例如 OpenAPI 或 JSON Schema,但有时也最好在 API 本身上动态传达这一点。

OPTIONS is the method used for that. You may know this HTTP method from CORS, but it’s general purpose is for clients to passively find out ‘What can I do here?’.
OPTIONS 是用于此目的的方法。您可能知道这个 HTTP 方法 CORS,但它的一般目的是让客户被动地发现“我能在这里做什么?

All HTTP clients typically support making OPTIONS request. For example with fetch():
所有 HTTP 客户端通常都支持发出 OPTIONS 请求。例如,使用 fetch()

const response = await fetch(
  'https://example.org',
  {method: 'OPTIONS'}
);

A basic OPTIONS response might might look like this:
基本的 OPTIONS 响应可能如下所示:

HTTP/1.1 204 No Content
Date: Mon, 23 Sep 2024 02:57:38 GMT
Server: KKachel/1.2
Allow: GET, PUT, POST, DELETE, OPTIONS

Based on the Allow header you can quickly tell which HTTP methods are available at a given endpoint. Many web frameworks emit this automatically and generate the list of methods dynamically per route, so chances are that you get this one for free.
根据 Allow 标头,您可以快速判断给定端点上有哪些 HTTP 方法可用。许多 Web 框架会自动发出此信息,并按路由动态生成方法列表,因此您很可能会免费获得此方法。

To find out if your server does, try running the command below (with your URL!):
要了解您的服务器是否这样做,请尝试运行以下命令(使用您的 URL!

curl -X OPTIONS http://localhost:3000/some/endpoint/

One nice thing you could do with the Allow header, is that you could also communicate access-control information on a very basic level. For example, you could only include DELETE and PUT if a user has write access to a resource.
您可以使用 Allow 标头做的一件好事是,您还可以在非常基本的级别上传达访问控制信息。例如,如果用户对资源具有写入访问权限,则只能包含 DELETEPUT

Accept and Accept-Encoding
接受和接受编码

There’s server other standard headers for discovery. Here’s an example showing a few at once:
还有服务器其他标准标头可供发现。下面是一个示例,一次显示几个:

HTTP/1.1 204 No Content
Date: Mon, 23 Sep 2024 02:57:38 GMT
Server: KKachel/1.2
Allow: GET, PUT, POST, DELETE, OPTIONS
Accept: application/vnd.my-company-api+json, application/json, text/html
Accept-Encoding: gzip,brotli,identity

You may already be familiar with Accept and Accept-Encoding from HTTP requests, but they can also appear in responses. Accept in a response lets you tell the client which kind of mimetypes are available at an endpoint. I like adding text/html to every JSON api endpoint and making sure that API urls can be opened in browsers and shared between devs for easy debugging.
您可能已经熟悉 HTTP 请求中的 AcceptAccept-Encoding,但它们也可能出现在响应中。Accept in a response 允许您告诉客户端端点上可用的 mimetype 类型。我喜欢将 text/html 添加到每个 JSON API 端点,并确保 API URL 可以在浏览器中打开并在开发人员之间共享,以便于调试。

The Accept-Encoding lets a client know in this case that they can compress their request bodies with either gzip or brotli (identity means no compression).
在这种情况下,Accept-Encoding 让客户端知道他们可以使用 gzipbrotli 压缩他们的请求正文( 身份意味着不压缩)。

Patching, posting and querying
修补、发布和查询

3 other headers that can be used are Accept-Patch, Accept-Post and Accept-Query. These three headers are used to tell a client what content-types are available for the PATCH, POST and QUERY http methods respectively.
其他 3 个可以使用的标头是 Accept-PatchAccept-PostAccept-Query 的 Accept-Query 中。这三个标头用于告诉客户端哪些内容类型可用于 PATCH、POSTQUERY http 方法。

For all of these headers, their values effectively dictate what valid values are for the Content-Type header when making the request.
对于所有这些标头,它们的值有效地规定了发出请求时 Content-Type 标头的有效值。

HTTP/1.1 204 No Content
Date: Mon, 23 Sep 2024 02:57:38 GMT
Server: KKachel/1.2
Allow: OPTIONS, QUERY, POST, PATCH
Accept-Patch: application/json-patch+json, application/merge-patch+json
Accept-Query: application/graphql
Accept-Post: multipart/form-data, application/vnd.custom.rpc+json

In the above response, the server indicates it supports both JSON Patch and JSON Merge Patch content-types in PATCH requests. It also suggests that GraphQL can be used via the QUERY method, and for POST it supports both standard file uploads and some custom JSON-based format.
在上述响应中,服务器表示它支持 JSON 补丁 以及 JSON 合并补丁 PATCH 请求中的内容类型。它还建议可以通过 QUERY 方法使用 GraphQL,对于 POST,它支持标准文件上传和一些基于 JSON 的自定义格式。

Typically you wouldn’t find all of these at the same endpoint, but I wanted to show a few examples together.
通常,您不会在同一端点找到所有这些,但我想一起展示几个示例。

Where’s PUT?  看跌期权在哪里?

Oddly, there’s no specific header for PUT requests. Arguably you could say that GET and PUT are symmetrical, so perhaps the Accept header kind of extends to both. But the spec is not clear on this.
奇怪的是,PUT 请求没有特定的标头。可以说, 您可以说 GETPUT 是对称的,所以也许 Accept 标头可以扩展到两者。但规范对此并不清楚。

I think the actual reality is that Accept-Patch was the first header in this category that really clearly defined this as a means of feature discovery on OPTIONS. Accept-Post and Accept-Query followed suit. I think Accept-Patch in OPTIONS was modelled after in-the-wild usage of Accept in OPTIONS, even though the HTTP specific doesn’t super clearly define this.
我认为实际的现实是,Accept-Patch 是该类别中第一个真正明确地将其定义为 OPTIONS 上功能发现手段的标头。Accept-PostAccept-Query 紧随其后。 我认为 OPTIONS 中的 Accept-Patch 是在 Accept 的野外用法之后建模的 在 OPTIONS 中,即使 HTTP 特定并没有非常清楚地定义这一点。

If I’m wrong with my interpretation here, I would love to know!
如果我在这里的解释有误,我很想知道!

Aside: If you’re wondering about DELETE, DELETE should never have a body, so all a user would need to know is can they delete, which you can see in the Allow header. If this is new to you to, read my other article about GET request bodies. Most of the information there is applicable to DELETE as well.
题外话:如果您想知道 DELETE,DELETE 永远不应该有正文 ,因此用户需要知道的只是他们是否可以删除,您可以在 Allow 标头中看到。如果这对您来说是新的, 请阅读我关于 GET 请求正文的另一篇文章。那里的大多数信息也适用于 DELETE

Linking to documentation
链接到文档

The OPTIONS response is also a great place to tell users where to find additional documentation. In the below example, I included both a machine-readable link to a documentation site, a link to an OpenAPI definition, and a message intended for humans in the response body:
OPTIONS 响应也是告诉用户在哪里可以找到其他文档的好地方。在下面的示例中,我在响应正文中包含了一个指向文档站点的机器可读链接、一个指向 OpenAPI 定义的链接以及一条面向人类的消息:

HTTP/1.1 200 OK
Date: Mon, 23 Sep 2024 04:45:38 GMT
Allow: GET, QUERY, OPTIONS
Link: <https://docs.example.org/api/some-endpoint>; rel="service-doc"
Link: <https://api.example.org/openapi.yml>; rel="service-desc" type="application/openapi+yaml"
Content-Type: text/plain

Hey there!

Thanks for checking out this API. You can find the docs for this
specific endpoint at: https://docs.example.org/api/some-endpoint

Cheers,
The dev team

I recommend keeping the response body as mostly informal and minimal any real information should probably just live on its own URL and be linked to.
我建议将响应正文保持为大部分非正式和最少,任何真实信息可能都应该存在于它自己的 URL 上并被链接到。

I used the service-doc and service-desc link relationships here, but you can of course use any of the IANA link relationship types here or a custom one. Also see the Web linking spec for more info.
我在这里使用了 service-docservice-desc 链接关系,但您当然可以在此处使用任何 IANA 链接关系类型或自定义关系类型。另请参阅 Web 链接规范以获取更多信息。

Obscure uses  晦涩难懂的用途

WebDAV usage  WebDAV 使用

WebDAV, CalDAV and CardDAV also use OPTIONS for feature discovery. For example:
WebDAV、CalDAV 和 CardDAV 也使用 OPTIONS 进行特征发现。 例如:

HTTP/1.1 204 No Content
Date: Mon, 23 Sep 2024 05:01:50 GMT
Allow: GET, PROPFIND, ACL, PROPPATCH, MKCOL, LOCK, UNLOCK
DAV: 1, 2, 3, access-control, addressbook, calendar-access

The server-wide asterisk request
服务器范围的星号请求

Normally HTTP requests are made to a path on the server, and the first line looks a bit like the following in HTTP/1.1:
通常,HTTP 请求是向服务器上的路径发出的,第一行看起来有点像 HTTP/1.1 中的以下内容:

GET /path HTTP/1.1

But, there are a few other “request line” formats that are rarely used. One of them lets you discover features available on an entire server, using the asterisk:
但是,还有一些其他很少使用的“请求行”格式。其中一种允许您使用星号发现整个服务器上可用的功能:

OPTIONS * HTTP/1.1

The asterisk here is not a path. Normally asterisks aren’t even allowed in URIs. Many HTTP clients (including fetch()) don’t even support this request.
这里的星号不是路径。通常,URI 中甚至不允许使用星号。许多 HTTP 客户端(包括 fetch())甚至不支持此请求。

Classic webservers like Apache and Nginx should support this. To try it out, use CURL
Apache 和 Nginx 等经典 Web 服务器应该支持此功能。要尝试一下,请使用 CURL

curl -vX OPTIONS --request-target '*' http://example.org

Final notes  最后的注意事项

If you have a reason to allow clients to discover features on an endpoint, consider using OPTIONS instead of a proprietary approach! As you can see in many of these examples, it’s especially useful if you use mimetypes well.
如果您有理由允许客户端发现端点上的功能,请考虑使用 OPTIONS 而不是专有方法!正如您在许多示例中看到的那样,如果您使用 mimetype,它特别有用 井。

If you have questions, other novel uses of OPTIONS or other ideas around feature discovery, you can respond via:
如果您有疑问、OPTIONS 的其他新颖用途或有关特征发现的其他想法,您可以通过以下方式回复:

Web mentions  网络提及

Reposts:  转发:

filmaj

Likes:  喜欢:

logical skeleton business Troels Thomsen